package com.xexun.gpstracker.my.activity;

import java.io.File;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;

import org.simple.eventbus.Subscriber;
import org.xutils.view.annotation.ViewInject;
import org.xutils.x;

import com.xexun.gpstracker.AppContext;
import com.xexun.gpstracker.channel.R;
import com.xexun.gpstracker.base.BaseActivity;
import com.xexun.gpstracker.common.CommonRestPath;
import com.xexun.gpstracker.common.Constants;
import com.xexun.gpstracker.component.MP3Recorder;
import com.xexun.gpstracker.fix.grant.PermissionsManager;
import com.xexun.gpstracker.fix.grant.PermissionsResultAction;
import com.xexun.gpstracker.inter.CommCallback;
import com.xexun.gpstracker.inter.HttpCallback;
import com.xexun.gpstracker.inter.OnProgressBarListener;
import com.xexun.gpstracker.pojo.ResponseData;
import com.xexun.gpstracker.util.CommUtil;
import com.xexun.gpstracker.util.HttpUtil;
import com.xexun.gpstracker.util.JsonHttpResponseHelper;
import com.xexun.gpstracker.util.Utils;
import com.xexun.gpstracker.view.NumberProgressBar;

public class DSPUploadActivity extends BaseActivity implements OnClickListener, OnProgressBarListener {
    @ViewInject(R.id.backBtn)
    private ImageButton backButton;
    @ViewInject(R.id.commitBtn)
    private Button commitButton;

    @ViewInject(R.id.music_name)
    private EditText musicName;
    @ViewInject(R.id.music)
    private ImageButton music;
    @ViewInject(R.id.record)
    private ImageButton record;
    @ViewInject(R.id.file_size)
    private TextView fileSize;
    @ViewInject(R.id.file_size_rec)
    private TextView fileSizeRec;
    @ViewInject(R.id.rec_time)
    private TextView recTime;
    @ViewInject(R.id.titleNameTV)
    private TextView titleName;
    @ViewInject(R.id.upload_music_frame)
    private FrameLayout uploadMusicLayout;
    @ViewInject(R.id.upload_record_frame)
    private FrameLayout uploadRecordLayout;
    @ViewInject(R.id.upload_progress_bar)
    private NumberProgressBar uploadProgressBar;

    private DSPHandler handler;
    private static final int COUNT_TIME = 0;
    private static final int WAITING_EXECUTE = 1;

    private String imei;
    private int position;

    private File uploadFile;
    public static final int MAX_FILE_SIZE = (1 << 20);//1MB
    private boolean isRecording = false;
    private MP3Recorder recorder;
    public static final int MAX_REC_SECONDS = 60;
    private int count = MAX_REC_SECONDS;
    private static final String FILE_PATH_REC = Utils.getAvailableStoragePath() + "audio/rec.mp3";

    private static final String TAG = DSPUploadActivity.class.getName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dsp_upload);
        x.view().inject(this);
        AppContext.getEventBus().register(this);

        handler = new DSPHandler(new WeakReference<>(this));

        backButton.setOnClickListener(this);
        commitButton.setOnClickListener(this);
        music.setOnClickListener(this);
        record.setOnClickListener(this);

        int type = getIntent().getIntExtra("type", 1);
        if (type == 1) {
            titleName.setText(getString(R.string.upload_records));
            uploadMusicLayout.setVisibility(View.GONE);
            uploadRecordLayout.setVisibility(View.VISIBLE);
        }

        imei = getIntent().getStringExtra("imei");
        position = getIntent().getIntExtra("position", 0);
    }

    @Override
    protected void onResume() {
        super.onResume();
        hideInputBoard();
    }

    @Override
    protected void onDestroy() {
        stopRecording();
        handler = null;
        super.onDestroy();
    }

    @Override
    public void onBackPressed() {
        if (count > 0 && count != MAX_REC_SECONDS) {
            CommUtil.showMsgShort(getString(R.string.upload_records_stop_rec));
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.backBtn:
                DSPUploadActivity.this.finish();
                break;
            case R.id.commitBtn:
                submit();
                break;
            case R.id.music:
                PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this,
                        new String[]{Constants.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        new PermissionsResultAction() {
                            @Override
                            public void onGranted() {
                                uploadProgressBar.setVisibility(View.GONE);
                                Intent intent = new Intent();
                                intent.setType("audio/*");
                                intent.setAction(Intent.ACTION_GET_CONTENT);
                                startActivityForResult(intent, 1);
                            }

                            @Override
                            public void onDenied(String permission) {
                                CommUtil.showMsgShort(getString(R.string.permission_refuse_file_note));
                            }
                        });
                break;
            case R.id.record:
                PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this,
                        new String[]{Manifest.permission.RECORD_AUDIO, Constants.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        new PermissionsResultAction() {
                            @Override
                            public void onGranted() {
                                recording();
                            }

                            @Override
                            public void onDenied(String permission) {
                                CommUtil.showMsgShort(getString(R.string.permission_refuse_record_note));
                            }
                        });
                break;
        }
    }

    private void recording() {
        uploadProgressBar.setVisibility(View.GONE);
        if (isRecording) {
            stopRecording();
        } else {
            isRecording = true;
            count = MAX_REC_SECONDS;
            if (recorder == null) {
                File file = new File(FILE_PATH_REC);
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdirs();
                }
                recorder = new MP3Recorder(file, MAX_FILE_SIZE);
            }
            try {
                recorder.start();
                handler.sendEmptyMessage(COUNT_TIME);
            } catch (Exception e) {
                Log.e(TAG, "开始录音出错", e);
            }
            fileSizeRec.setVisibility(View.GONE);
            record.setBackgroundResource(R.drawable.icon_rec_stop);
        }
    }

    private void stopRecording() {
        isRecording = false;
        if (recorder != null) {
            try {
                recorder.stop();
                recorder = null;
                Message msg = Message.obtain(handler);
                msg.what = WAITING_EXECUTE;
                msg.obj = new CommCallback() {
                    @Override
                    public void execute() {
                        uploadFile = new File(FILE_PATH_REC);
                        if (!uploadFile.exists()) {
                            uploadFile = null;
                            CommUtil.showMsgShort(getString(R.string.upload_records_failed));
                        } else {
                            fileSizeRec.setText(CommUtil.prettyFileSize(uploadFile.length()));
                            fileSizeRec.setVisibility(View.VISIBLE);
                            SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault());
                            musicName.setText(getString(R.string.upload_records) + "_" + fmt.format(new Date()));
                        }
                        count = 0;
                    }
                };
                //必须等待录音线程完全结束后才能取得到正确的文件大小
                handler.sendMessageDelayed(msg, 200);
            } catch (Exception e) {
                Log.e(TAG, "停止录音出错", e);
                CommUtil.showMsgShort(getString(R.string.upload_records_failed));
            }
        }
        count = 0;
        recTime.setVisibility(View.GONE);
        record.setBackgroundResource(R.drawable.icon_rec);
        if (handler != null) {
            handler.removeMessages(COUNT_TIME);
        }
    }

    private void submit() {
        hideInputBoard();
        if (count > 0 && count != MAX_REC_SECONDS) {
            CommUtil.showMsgShort(getString(R.string.upload_records_stop_rec));
            return;
        }
        String muName = musicName.getText().toString().trim();
        if (CommUtil.isBlank(muName) || uploadFile == null || muName.length() > 30) {
            CommUtil.showMsgShort(getString(R.string.upload_songs_note_blank));
            return;
        }
        if (uploadFile.length() > MAX_FILE_SIZE * 1.1) {
            CommUtil.showMsgShort(getString(R.string.upload_songs_note_type));
            return;
        }
        uploadProgressBar.setVisibility(View.VISIBLE);
        HttpCallback callback = new HttpCallback() {
            @Override
            public void onStart() {
                commitButton.setEnabled(false);
            }

            @Override
            public void onSuccess(ResponseData obj) throws Exception {
                if (obj.getRetcode() == 1) {
                    CommUtil.showMsgShort(String.format(getString(R.string.success), getString(R.string.upload)));
                    finish();
                } else if (CommUtil.isNotBlank(obj.getMsg())) {
                    CommUtil.showMsgShort(obj.getMsg());
                    uploadProgressBar.setVisibility(View.GONE);
                    commitButton.setEnabled(true);
                }
            }

            @Override
            public void onFailure(String message) throws Exception {
                CommUtil.showMsgShort(String.format(getString(R.string.failed), getString(R.string.upload)));
                uploadProgressBar.setVisibility(View.GONE);
                commitButton.setEnabled(true);
            }

            @Override
            public void onLoading(long total, long current, boolean isDownloading) {
                uploadProgressBar.setProgress((int) (current * 100 / total));
            }
        };
        Map<String, Object> params = new HashMap<>();
        params.put("imei", imei);
        params.put("position", position + 1);
        params.put("myfile", uploadFile);
        params.put("name", muName);
        HttpUtil.postMulti(CommonRestPath.appAudioUpload(), params, new JsonHttpResponseHelper(callback).getHandler());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            Uri uri = data.getData();
            Log.d("uri", uri.toString());
            try {
                String uploadFilePath = Utils.getRealFilePath(this, uri);
                if (CommUtil.isNotBlank(uploadFilePath)
                        && ".MP3".equalsIgnoreCase(uploadFilePath.substring(uploadFilePath.lastIndexOf('.')))
                        && (uploadFile = new File(uploadFilePath)).exists()
                        && uploadFile.length() < MAX_FILE_SIZE) {
                    String fName = uploadFile.getName().substring(0, uploadFile.getName().lastIndexOf('.'));
                    musicName.setText(fName.replaceAll("\\:| |", ""));
                    musicName.setSelection(fName.length());
                    music.setBackgroundResource(R.drawable.icon_music);
                    fileSize.setText(CommUtil.prettyFileSize((double) uploadFile.length()));
                    fileSize.setVisibility(View.VISIBLE);
                } else {
                    CommUtil.showMsgShort(getString(R.string.upload_songs_note_type));
                }
            } catch (Exception e) {
                Log.e(DSPUploadActivity.class.getName(), "选择文件出错", e);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
    }

    @Override
    public void onProgressChange(int current, int max) {

    }

    @Subscriber(tag = Constants.EVENT_TAG_AUTO_STOP_RECORD)
    private void onRecordStop() {
        stopRecording();
    }

    private static class DSPHandler extends Handler {
        private DSPUploadActivity activity;

        public DSPHandler(WeakReference<DSPUploadActivity> activity) {
            this.activity = activity.get();
        }

        @Override
        public void handleMessage(Message msg) {
            if (activity == null) {
                return;
            }
            switch (msg.what) {
                case COUNT_TIME:
                    if (activity.count <= 0) {
                        activity.stopRecording();
                    } else {
                        activity.recTime.setText(CommUtil.prettyTimeCounting(activity.count));
                        activity.recTime.setVisibility(View.VISIBLE);
                        sendEmptyMessageDelayed(COUNT_TIME, 1000);
                    }
                    activity.count--;
                    break;
                case WAITING_EXECUTE:
                    if (msg.obj instanceof CommCallback) {
                        CommCallback callback = (CommCallback) msg.obj;
                        callback.execute();
                    }
                    break;
            }
        }
    }
}
